.PHONY = all install clean
BUILD_DIR ?= build/obj

# Visits the soruce directory recursively and fills $(cflags), $(objs) and $(libs).
# $(1): The target source dir.
# $(2): The build dir.
define visit-subdir
$(eval objs-y :=)
$(eval libs-y :=)
$(eval build_dir := $(2)/$(1))
$(eval subdirs-y :=)
$(eval cflags-y :=)
$(eval global-cflags-y :=)
$(eval global-includes-y :=)
$(eval include $(1)/build.mk)
$(eval build_mks += $(1)/build.mk)
$(eval objs     += $(addprefix $(2)/$(1)/, $(objs-y)))
$(eval all_objs += $(addprefix $(2)/$(1)/, $(objs-y)))
$(eval libs += $(libs-y))
$(eval cflags += $(cflags-y))
$(eval CFLAGS += $(global-cflags-y))
$(eval INCLUDES += $(global-includes-y))
$(eval $(foreach subdir, $(subdirs-y), \
	$(eval $(call visit-subdir,$(1)/$(subdir),$(2)))))
endef

 # Enumerate kernel object files.
 all_objs :=
 objs :=
 	$(eval $(call visit-subdir,src,$(BUILD_DIR)))
 kernel_objs := $(objs)
 kernel_objs += $(LIBC_PATH)

$(info objs: $(objs))
#target name

kernel_image := build/bin/kernel.elf

#global directory defined
TOPDIR       = $(shell pwd)
SRCDIR	 	= $(TOPDIR)/src
LIBDIR      = $(TOPDIR)/lib
OBJECTDIR    = $(TOPDIR)/build/obj
INCLUDES   = -I $(TOPDIR)/include
kernel_ld = $(TOPDIR)/src/link.ld
OUTDIR =  $(TOPDIR)/build/bin

# 延时变量, 只有第一次定义赋值才成功.而该变量在/etc/profile中. 已定义为arm-linux-gnueabihf-
CROSS_COMPILE ?=aarch64-none-elf-
# 定义延时变量
# e.g. as = arm-linux-gnueabihf-as
ASM		= $(CROSS_COMPILE)as
LD		= $(CROSS_COMPILE)ld
CC		= $(CROSS_COMPILE)gcc
CPP		= $(CC) -E
AR		= $(CROSS_COMPILE)ar
NM		= $(CROSS_COMPILE)nm
GDB     = $(CROSS_COMPILE)gdb 
STRIP		= $(CROSS_COMPILE)strip
OBJCOPY		= $(CROSS_COMPILE)objcopy
OBJDUMP		= $(CROSS_COMPILE)objdump
 
# export全局变量, 可供其他Makefile使用
export AS LD CC CPP AR NM
export STRIP OBJCOPY OBJDUMP
export PROGRESS := printf "  \\033[1;96m%8s\\033[0m  \\033[1;m%s\\033[0m\\n"
board ?= rpi4
ifeq ($(board), rpi3)
	COPS += -DCONFIG_BOARD_PI3B
	QEMU_FLAGS  += -machine raspi3b
else ifeq ($(board), rpi4)
	COPS += -DCONFIG_BOARD_PI4B
	QEMU_FLAGS  += -machine raspi4
endif

QEMU_OPT = qemu-system-aarch64 $(QEMU_FLAGS) -kernel build/bin/kernel.bin  -smp 4 -m 1G -display none   -serial mon:stdio  -nic user,tftp=$(OUTDIR)

#defaut target:compile the currrent dir file and sub dir
all:  $(kernel_image)
 #
 #  Kernel Build Rules
 # 
 $(kernel_image): $(kernel_objs) $(kernel_ld)
	mkdir -p build/bin
#	$(LD) $(ARCH_LDFLAGS) $(LDFLAGS) -Map $(@:.elf=.map) -o $@.debug $(kernel_objs)
	$(LD) $(LDFLAGS) --script=$(kernel_ld) -Map $(@:.elf=.map) -o $@.tmp $(kernel_objs)  
	$(OBJCOPY) -S $@.tmp $@
	$(OBJDUMP) -t -S $@.tmp > $(BUILD_DIR)/kernel.sym
	$(OBJCOPY) build/bin/kernel.elf -O binary build/bin/kernel.bin
	cp -ravf  build/bin/kernel.bin  ~/share/tftpboot/
 
 $(BUILD_DIR)/%.o: %.c
	$(PROGRESS) "$(CC)" $<
	mkdir -p $(@D)
#	$(CC) $(CFLAGS) $(C_FLAG_KERN) $(INCLUDEDIR)  -c -o $@ $<
	$(CC) $(CFLAGS) $(SANITIZER) $(KERNEL_CFLAGS) $(INCLUDES) -DKERNEL  -o $@ -c $< -MD -MF $(@:.o=.deps) -J $(@:.o=.json)
 
 $(BUILD_DIR)/%.o: %.S
	$(PROGRESS) "$(CC)" $<
	mkdir -p $(@D)
#	$(CC) $(CFLAGS) $(C_FLAG_KERN) $(INCLUDEDIR) -c -o $@ $< 
	$(CC) $(CFLAGS) $(SANITIZER) $(KERNEL_CFLAGS) $(INCLUDES) -o $@ -c $< -MD -MF $(@:.o=.deps) -J $(@:.o=.json)
 
clean:
	rm -rvf build
	rm -rvf *.bin

run:
	$(QEMU_OPT)

debug:
	$(QEMU_OPT) -s -S

trace:
	cgdb -d $(GDB) -x "cgdb.script"

